/* jshint esversion: 6 */
import Cookies from 'js-cookie'
import cryptoJs from 'crypto-js'
import JSEncrypt from 'jsencrypt'
import { forEach, hasOneOf, objEqual } from '@/libs/tools'

export const holdTime = 6 // Cookies保存时间
export const tmpSymmkeyIndex = ''
export const tmpPublicKey = 0
export const tmpSymmkey = ''

export const setSymmKeyIndex = (symmkeyIndex) => {
  Cookies.set('symmkeyIndex', symmkeyIndex, {expires: holdTime})
}

export const getSymmKeyIndex = () => {
  const symmkeyIndex = Cookies.get('symmkeyIndex')
  if (symmkeyIndex) return parseInt(symmkeyIndex)
  else return false
}

export const setSymmKey = (symmkey) => {
  Cookies.set('symmkey', symmkey, {expires: holdTime})
}

export const getSymmKey = () => {
  const symmkey = Cookies.get('symmkey')
  if (symmkey) return symmkey
  else return false
}

export const setPublicKey = (publicKey) => {
  Cookies.set('publicKey', publicKey, {expires: holdTime})
}

export const getPublicKey = () => {
  const publicKey = Cookies.get('publicKey')
  if (publicKey) return publicKey
  else return false
}
export const getToken = () => {
  var token = false
  if (getSymmKey() && getSymmKeyIndex() && getPublicKey()) {
    token = true
  }
  return token
}
/**
 * 生成登陆密钥
 */
export const generateAesKey = () => {
  let wordArray = cryptoJs.lib.WordArray.random(8)
  let symmkey = cryptoJs.enc.Hex.stringify(wordArray)
  setSymmKey(symmkey)
  return symmkey
}

/**
 * 登陆信息加密
 */
export const rsaEncrypt = (data, publicKey) => {
  let encrypt = new JSEncrypt()
  encrypt.setPublicKey(publicKey)
  // return { data: encrypt.encrypt(window.JSON.stringify(data)) }
  return encrypt.encrypt(window.JSON.stringify(data))
}
/**
 * [tasilyEncode aes加密]
 * @param  {[JSON]}   data    [待加密JSON对象]
 * @param  {[int]}    index   [服务器端存放堆成密钥的索引]
 * @param  {[String]} symmKey [堆成密钥]
 * @return {[JSON]}           [加密后的JSON对象]
 */
export const tasilyEncode = (data, index, symmKey) => {
  if (!data) data = JSON.stringify({ index: index })
  if (typeof (data) === 'object') data = JSON.stringify(data)
  var value = aesEncrypt(encodeURIComponent(data), symmKey)
  return JSON.stringify({ content: value.toString(), index: index + '_web' })
}

/**
 * [aesEncrypt aes加密]
 * @param  {[JSON]}   data    [待加密的JSON对象]
 * @param  {[String]} symmkey [对称密钥]
 * @return {[type]}           [加密后的JSON对象]
 */
export const aesEncrypt = (data, symmkey) => {
  var key = cryptoJs.enc.Utf8.parse(symmkey)
  var iv = cryptoJs.enc.Utf8.parse('0102030405060708')
  var srcs = cryptoJs.enc.Utf8.parse(data)
  return cryptoJs.AES.encrypt(srcs, key, {
    iv: iv,
    mode: cryptoJs.mode.CBC,
    padding: cryptoJs.pad.Pkcs7
  })
}

/**
 * [aesDecrypt aes解密算法]
 * @param  {[JSON]}   data    [解密字符串]
 * @param  {[String]} symmKey [对称密钥]
 * @return {[JSON]}           [返回解密后的字符串]
 */
export const aesDecrypt = (data, symmkey) => {
  var key = cryptoJs.enc.Utf8.parse(symmkey)
  var iv = cryptoJs.enc.Utf8.parse('0102030405060708')
  var decrypted = cryptoJs.AES.decrypt(data, key, {
    iv: iv,
    mode: cryptoJs.mode.CBC,
    padding: cryptoJs.pad.Pkcs7
  })
  if (decrypted) {
    return decrypted.toString(cryptoJs.enc.Utf8)
  }
}

/**
 * [fixMenus 删选出父类叶子节点，然后去递归子节点，组织数据成{children:[{}]} 格式]
 * @param  {[type]} menus            [description]
 * @param  {[type]} fromParentIsNull ['yes' 时，只有当parent 为null时才能作为第一级目录]
 * @return {[type]}                  [description]
 */
export const fixMenus = (menus, fromParentIsNull) => {
  let parents = []
  menus.map((obj, idx) => {
    obj.children = []
  })
  if (fromParentIsNull && fromParentIsNull === 'yes') parents = menus.filter(menu => !menu.parent && !menu.pId)
  else {
    parents = menus.filter(menu => {
      if (!menu.parent && !menu.pId) return true
      var i = 0
      var length = menus.length
      for (; i < length; i++) {
        var tmp = menus[i]
        if ((menu.parent && tmp.id === menu.parent.id) || (menu.pId && tmp.id === menu.pId)) return false
        // else if () return true
      }
      return true
    })
  }
  parents.map((obj, idx) => {
    arrageMenus(menus, obj)
  })
  return parents
}

/**
 * [arrageMenus 递归menus, 生成格式为{[children: []]}]
 * @param  {[type]} menus  [description]
 * @param  {[type]} parent [description]
 * @return {[type]}        [description]
 */
export const arrageMenus = (menus, parent) => {
  let pId = parent.id
  menus.map((obj, index) => {
    let objPid = obj.parent ? obj.parent.id : (obj.pId ? obj.pId : 0)
    if (objPid === pId) {
      parent.children.push(arrageMenus(menus, obj))
    }
  })
  return parent
}

/**
 * @param {Array} routeMetched 当前路由metched
 * @returns {Array}
 */
export const getBreadCrumbList = (routeMetched, homeRoute) => {
  let res = routeMetched.filter(item => {
    return item.meta === undefined || !item.meta.hide
  }).map(item => {
    let obj = {
      icon: (item.meta && item.meta.icon) || '',
      name: item.name,
      meta: item.meta
    }
    return obj
  })
  res = res.filter(item => {
    return !item.meta.hideInMenu
  })
  return [Object.assign(homeRoute, { to: homeRoute.path }), ...res]
}

/**
 * @description 本地存储和获取标签导航列表
 */
export const setTagNavListInLocalstorage = list => {
  localStorage.tagNaveList = JSON.stringify(list)
}

/**
 * @param {Array} list 通过路由列表得到菜单列表
 * @returns {Array}
 */
export const getMenuByRouter = (list, access) => {
  let res = []
  forEach(list, item => {
    if (!item.meta || (item.meta && !item.meta.hideInMenu)) {
      let obj = {
        icon: (item.meta && item.meta.icon) || '',
        name: item.name,
        meta: item.meta
      }
      if ((hasChild(item) || (item.meta && item.meta.showAlways)) && showThisMenuEle(item, access)) {
        obj.children = getMenuByRouter(item.children, access)
      }
      if (item.meta && item.meta.href) obj.href = item.meta.href
      if (showThisMenuEle(item, access)) res.push(obj)
    }
  })
  return res
}

export const hasChild = (item) => {
  return item.children && item.children.length !== 0
}

const showThisMenuEle = (item, access) => {
  if (item.meta && item.meta.access && item.meta.access.length) {
    if (hasOneOf(item.meta.access, access)) return true
    else return false
  } else return true
}
/**
 * @returns {Array} 其中的每个元素只包含路由原信息中的name, path, meta三项
 */
export const getTagNavListFromLocalstorage = () => {
  const list = localStorage.tagNaveList
  return list ? JSON.parse(list) : []
}

/**
 * @param {Array} routers 路由列表数组
 * @description 用于找到路由列表中name为home的对象
 */
export const getHomeRoute = routers => {
  let i = -1
  let len = routers.length
  let homeRoute = {}
  while (++i < len) {
    let item = routers[i]
    if (item.children && item.children.length) {
      let res = getHomeRoute(item.children)
      if (res.name) return res
    } else {
      if (item.name === 'home') homeRoute = item
    }
  }
  return homeRoute
}

/**
 * 判断打开的标签列表里是否已存在这个新添加的路由对象
 */
export const routeHasExist = (tagNavList, routeItem) => {
  let len = tagNavList.length
  let res = false
  doCustomTimes(len, (index) => {
    if (routeEqual(tagNavList[index], routeItem)) res = true
  })
  return res
}

/**
 * @param {Number} times 回调函数需要执行的次数
 * @param {Function} callback 回调函数
 */
export const doCustomTimes = (times, callback) => {
  let i = -1
  while (++i < times) {
    callback(i)
  }
}
/**
 * @description 根据name/params/query判断两个路由对象是否相等
 * @param {*} route1 路由对象
 * @param {*} route2 路由对象
 */
export const routeEqual = (route1, route2) => {
  const params1 = route1.params || {}
  const params2 = route2.params || {}
  const query1 = route1.query || {}
  const query2 = route2.query || {}
  return (route1.name === route2.name) && objEqual(params1, params2) && objEqual(query1, query2)
}

/**
 * 权鉴
 * @param {*} name 即将跳转的路由name
 * @param {*} access 用户权限数组
 * @param {*} routes 路由列表
 * @description 用户是否可跳转到该页
 */
export const canTurnTo = (name, access, routes) => {
  const routePermissionJudge = (list) => {
    return list.some(item => {
      if (item.children && item.children.length) {
        return routePermissionJudge(item.children)
      } else if (item.name === name) {
        return hasAccess(access, item)
      }
    })
  }

  return routePermissionJudge(routes)
}

/**
 * @param {*} access 用户权限数组，如 ['super_admin', 'admin']
 * @param {*} route 路由列表
 */
const hasAccess = (access, route) => {
  if (route.meta && route.meta.access) return hasOneOf(access, route.meta.access)
  else return true
}

/**
 * @param {*} list 现有标签导航列表
 * @param {*} newRoute 新添加的路由原信息对象
 * @description 如果该newRoute已经存在则不再添加
 */
export const getNewTagList = (list, newRoute) => {
  const { name, path, meta } = newRoute
  let newList = [...list]
  if (newList.findIndex(item => item.name === name) >= 0) return newList
  else newList.push({ name, path, meta })
  return newList
}

/**
 * @param {Array} list 标签列表
 * @param {String} name 当前关闭的标签的name
 */
export const getNextRoute = (list, route) => {
  let res = {}
  if (list.length === 2) {
    res = getHomeRoute(list)
  } else {
    const index = list.findIndex(item => routeEqual(item, route))
    if (index === list.length - 1) res = list[list.length - 2]
    else res = list[index + 1]
  }
  return res
}

/**
 * [collatingTreeData 整理树数据]
 * @param  {[type]} item [description]
 * @param  {[type]} data [description]
 * @return {[type]}      [description]
 */
export const collatingTreeData = (data, parent) => {
  var beforeFinishing = []
  if (parent) {
    beforeFinishing = parent
    beforeFinishing.children = []
  }
  data.map(function (item, index) {
    item.title = item.name
    if (!item.pId && !parent) {
      item.children = []
      beforeFinishing.push(collatingTreeData(data, item))
    } else if (parent && parent.id === item.pId) {
      var oneItem = collatingTreeData(data, item)
      if (oneItem) {
        beforeFinishing.children.push(oneItem)
      }
    }
  })
  return beforeFinishing
}
